#include "operand.h"
#include "tree.h"
#include "assert.h"

OpTreeNode::OpTreeNode(Operand* current, OpTreeNode* left, OpTreeNode* right)
{
	this->current = current;
	this->left = left;
	this->right = right;
}

OpTreeNode::OpTreeNode(Operand* current, OpTreeNode* left, Operand* rightOp)
{
	this->current = current;
	this->left = left;
	this->right = new OpTreeNode(rightOp, (OpTreeNode*) NULL, (OpTreeNode*) NULL);
}

OpTreeNode::OpTreeNode(Operand* current, Operand* leftOp, OpTreeNode* right)
{
	this->current = current;
	this->left = new OpTreeNode(leftOp, (OpTreeNode*) NULL, (OpTreeNode*) NULL);
	this->right = right;
}

OpTreeNode::OpTreeNode(Operand* current, Operand* leftOp, Operand* rightOp)
{
	this->current = current;
	this->left = new OpTreeNode(leftOp, (OpTreeNode*) NULL, (OpTreeNode*) NULL);
	this->right = new OpTreeNode(rightOp, (OpTreeNode*) NULL, (OpTreeNode*) NULL);
}

int OpTreeNode::Execute()
{
	int value = MAX32;

	switch( current->GetType() )
	{
	case OPERAND_REG:
	case OPERAND_WIRE:
	case OPERAND_VAR:
	case OPERAND_CONST:
		value = current->GetValue();
		break;
	case OPERAND_ASSIGN:
		left->SetValue(right->GetValue());
		break;
	case OPERAND_NEG:
		value = (right->GetCurrent()->GetValue() + 1)%2;
		break;
	case OPERAND_PLUS:
		value = left->Execute() + right->Execute();
		break;
	case OPERAND_MINUS:
		value = left->Execute() - right->Execute();
		break;
	case OPERAND_MUL:
		value = left->Execute() * right->Execute();
		break;
	case OPERAND_DIV:
		value = left->Execute() / right->Execute();
		break;
	case OPERAND_POSEDGE:
		if ( right->GetCurrent()->GetState() == STATE_POSEDGE ) value = 1;
		else value = 0;
		break;
	case OPERAND_NEGEDGE:
		if ( right->GetCurrent()->GetState() == STATE_NEGEDGE ) value = 1;
		else value = 0;
		break;
	default:
		assert(1);
		break;
	}

	return value;
}

void OpTreeNode::Print()
{
	if(left) left->Print();
	current->Print();
	if(right) right->Print();
}
